#include "MyMessage.h"
#include "Timer.h"

module routeDiscoveryC{

  uses{
    interface Boot;
    interface AMPacket;
    interface Packet;
    interface PacketAcknowledgements;
    interface AMSend;
    interface SplitControl;
    interface Receive;
//     interface Timer<TMilli> as MilliTimer;
//     interface Read<uint16_t>;
  }
}

implementation{

    uint16_t counter=0;
    uint8_t neighbours_count=0;
    uint16_t rec_id;
    message_t packet;
    messaggio_t* rpack;
    task void sendRREQ();
    enum {
	ARRAY_SIZE = 100
    };

  
    uint16_t received_beacon[ARRAY_SIZE*10]; 	
    uint8_t neighbours[ARRAY_SIZE];   
    
    /*teniamo in memoria l'hop count per ogni pacchetto ricevuto destinato ad un certo nodo.
    Per ogni destinazione si fa il forward del pacchetto solo se il suo hop count è minore (<=) del
    valore già memorizzato*/
    uint8_t hop_counts[ARRAY_SIZE];  

    
    //***************** Interfaccia boot ********************//
    event void Boot.booted(){
	if (TOS_NODE_ID==7){
	    dbg("boot","Sono acceso\n");
	}
	call SplitControl.start();
    }

    //***************** Interfaccia SplitControl ********************//
    event void SplitControl.startDone(error_t err){
	if(err == SUCCESS){
	    //call MilliTimer.startPeriodic( 500 );
	    if (TOS_NODE_ID==7){
		
	    } 
	}
	else{
	    call SplitControl.start();
	}
    }
  
    event void SplitControl.stopDone(error_t err){}


//     //***************** Interfaccia TMilli ********************//
//     event void MilliTimer.fired() {
// 	post sendBeacon();
//     }
  
    //***************** Task send request ********************//
    task void sendRREQ() {
	uint8_t len;
	messaggio_t* mess=(messaggio_t*)(call Packet.getPayload(&packet,&len));
	mess->msg_type=0;
	mess->source_id=TOS_NODE_ID;
	mess->dest_id=81;
	mess->hop_count=1;
	mess->route[0]=TOS_NODE_ID;
	hop_counts[TOS_NODE_ID]=1;
	dbg("tx","Sto mandando RREQ...\n");
	call PacketAcknowledgements.noAck( &packet );
	if(call AMSend.send(TOS_BCAST_ADDR,&packet,sizeof(messaggio_t)) == SUCCESS){
	}
    } 

    //***************** Task forward RREQ ********************//
    task void forwardRREQ() {
		
	nx_uint8_t count;
	nx_uint16_t dest;
	count=rpack->hop_count;
	rpack->route[count]=TOS_NODE_ID;
	hop_counts[dest]=count;
	rpack->hop_count=count+1;
	
	dbg("tx","Forwarding RREQ...\n");
	call PacketAcknowledgements.noAck( &packet );
	if(call AMSend.send(TOS_BCAST_ADDR,&packet,sizeof(messaggio_t)) == SUCCESS){
	}
    } 

//***************** Task send route response ********************//
    task void sendRREP() {
	//WORK IN PROGRESS
// 	uint8_t len;
// 	uint8_t count;    
// 	nx_uint16_t dest;
// 	messaggio_t* mess=(messaggio_t*)(call Packet.getPayload(&packet,&len));
// 	mess->msg_type=1;
// 	mess->source_id=TOS_NODE_ID;
// 	mess->dest_id=rpack->dest_id;
// 	dest=rpac->route[route]
// 	count=rpack->hop_count;
// 	dest=rpack
// 	mess->hop_count=1;
// 	dbg("tx","Sto mandando RREP...\n");
// 	call PacketAcknowledgements.noAck( &packet );
// 	if(call AMSend.send(rpack->,&packet,sizeof(messaggio_t)) == SUCCESS){
// 	   
// 	}
    } 

       

    //******************Stampa a video**********************//
    void stampa(){
	uint8_t i;
	for (i=0;i<ARRAY_SIZE;i++){
	    dbg("rx","array %i = %i \n",i,neighbours[i]);
	}
// 	for (i=0;i<ARRAY_SIZE;i++){
// 	    dbg("rx","array %i = %i \n",i,received_beacon[i]);
// 	}
	dbg("rx","Numero di vicini: %i\n", neighbours_count);  
    } 


    //*********************+ Interfaccia Send ****************//
    event void AMSend.sendDone(message_t* buf,error_t err){
	if(&packet == buf && err == SUCCESS ){
	    if ( TRUE ) {
	    } else {
		dbg_clear("tx","fallito\n");
	    }
	}
    }


    //***************************** Interfaccia Receive *****************//
    event message_t* Receive.receive(message_t* buf,void* payload, uint8_t len){
	messaggio_t* mess=(messaggio_t*)payload;
	rpack = mess;
	//prima di tutto distinguiamo tra una RREQ e una RREP
	if ( rpack->msg_type == RREQ ) {
	    //il pacchetto è una RREQ
	    //se il pacchetto è giunto a destinazione il nodo manda una RREP
	    if ( rpack->dest_id == TOS_NODE_ID ) {
		post sendRREP();	    
	    }
	    //altrimenti se il pacchetto ha un hop count maggiore di quello che il
	    //nodo ha già memorizzato per la destinazione, il pacchetto viene scartato.
	    //Se invece l'hop count è minore o uguale viene forwardato
	    else {
		if ( rpack->hop_count > hop_counts[rpack->dest_id] ) {
		    //caso del pacchetto scartato
		    rpack = NULL; //discard message
		}
		else {
		    //caso del pacchetto forwardato
		    post forwardRREQ();
		}
	    }
	}
	else {
	    //il messaggio è di tipo RREP
	    if ( rpack->dest_id == TOS_NODE_ID ) {
		//RREP è giunta al nodo sorgente iniziale
		//post RREPreceived();	    
	    }
	    else {
		//RREP non è ancora giunta a destinazione e viene forwardata
		//post forwardRREP();
	    }
	}
    }

/*
	if(neighbours[rec_id]!=1){
	    neighbours[rec_id]=1;
	    neighbours_count++;
	}
	received_beacon[counter]=rec_id;
	if ( TOS_NODE_ID == 7 ) {
	    dbg_clear("rx","counter: %i\n",counter);
	    dbg_clear("rx","rec_id: %i\n",rec_id);
	    stampa();
        }	
	counter++;
	return buf;
    }
*/

 
    //****************** Task send response *****************//
	/*  task void sendResp() {
	    call Read.read();
    }
    */
    //************************* Interafaccia Read **********************//
    /*  event void Read.readDone(error_t result, uint16_t data) {
	uint8_t len;
	messaggio_t* mess=(messaggio_t*)(call Packet.getPayload(&packet,&len));
	mess->msg_type = RESP;
	mess->msg_id = rec_id;
	mess->value = data;
	dbg("rx","Sto inviando la risposta\n");
	call PacketAcknowledgements.requestAck( &packet );
	if(call AMSend.send(1,&packet,sizeof(messaggio_t)) == SUCCESS){
    }
    }
*/
	
}
